package com.cgc.venus.server.log.service;
import com.cgc.venus.server.core.base.AbstractBaseService;
import com.cgc.venus.server.core.bean.response.VenusResponseStatus;
import com.cgc.venus.server.core.es.BaseElasticsearch;
import com.cgc.venus.server.core.exception.VenusException;
import com.cgc.venus.server.core.k8s.inter.K8sManageService;
import com.cgc.venus.server.core.utils.DateUtil;
import com.cgc.venus.server.core.utils.StringUtil;
import com.cgc.venus.server.log.bean.AppLog;
import com.cgc.venus.server.log.inter.AppLogService;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.utils.HttpClientUtils;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.Client;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.net.URL;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Created by Administrator on 2017/11/20.
 */
@Service
public class AppLogServiceImpl extends AbstractBaseService implements AppLogService{
    @Autowired
    public K8sManageService k8sManageService;

    @Autowired
    private BaseElasticsearch baseElasticsearch;
    private final int PAGE_SIZE=100;

    static class miTM implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }
        public boolean isServerTrusted(
                java.security.cert.X509Certificate[] certs) {
            return true;
        }
        public boolean isClientTrusted(
                java.security.cert.X509Certificate[] certs) {
            return true;
        }
        public void checkServerTrusted(
                java.security.cert.X509Certificate[] certs, String authType)
                throws java.security.cert.CertificateException {
            return;
        }
        public void checkClientTrusted(
                java.security.cert.X509Certificate[] certs, String authType)
                throws java.security.cert.CertificateException {
            return;
        }
    }

    private static void trustAllHttpsCertificates() throws Exception {
        javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
        javax.net.ssl.TrustManager tm = new miTM();
        trustAllCerts[0] = tm;
        javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext
                .getInstance("SSL");
        sc.init(null, trustAllCerts, null);
        javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc
                .getSocketFactory());
    }



    /**
     *
     * @param podName
     * @param timeStart
     * @param timeEnd
     * @param queryKey
     * @param currentPage
     * @return
     */
    @Override
    public AppLog queryAppLog(String namespaceName,String podName, String timeStart, String timeEnd, String queryKey, int currentPage) throws VenusException {
        //System.out.println("namespaceName:"+namespaceName);
        //System.out.println("podName:"+podName);
        Client client=null;
        try{
            try {
                client=baseElasticsearch.getEsDataSource().getClient();
            } catch (Exception e) {
                e.printStackTrace();
                throw new VenusException(VenusResponseStatus.LOG_EXCEPTION, "获取日志es客户端异常!");
            }
            if (StringUtil.isEmpty(podName)) {
                throw new VenusException(VenusResponseStatus.NO_CONTENT, "应用实例为空!");
            }
            BoolQueryBuilder bq= QueryBuilders.boolQuery();
            bq.must(QueryBuilders.termsQuery("kubernetes.namespace_name", namespaceName));
            bq.must(QueryBuilders.termsQuery("kubernetes.pod_name", podName));
            if(!StringUtil.isEmpty(queryKey)){
                bq.must(QueryBuilders.queryStringQuery(queryKey));
            }
            String ds="";
            String de="";
            try {
                ds= DateUtil.dealDateFormat(timeStart);
                de= DateUtil.dealDateFormat(timeEnd);
            } catch (ParseException e) {
                throw new VenusException(VenusResponseStatus.LOG_EXCEPTION, "时间格式有误!");
            }
            bq.must(QueryBuilders.rangeQuery("@timestamp").from(ds).to(de));
            SortOrder sortOrder=SortOrder.ASC;;

            SearchRequestBuilder srb = client.prepareSearch("logstash-*")
                    .setTypes("fluentd")
                            //按时间降序号
                    .addSort("@timestamp", sortOrder)
                    .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                            // 设置查询数据的位置,分页用
                    .setFrom((currentPage - 1) * PAGE_SIZE)
                            // 设置查询结果集的最大条数
                    .setSize(PAGE_SIZE)
                            // 设置是否按查询匹配度排序
                    .setExplain(true);
            // 最后就是返回搜索响应信息
            srb.setQuery(bq);

            SearchResponse response =srb.execute().actionGet();
            SearchHits searchHits = response.getHits();
            SearchHit[] hits = searchHits.getHits();
            AppLog appLog=new AppLog();
            appLog.setTotalNum(searchHits.getTotalHits());
            if(appLog.getTotalNum()>0){
                Long r0=appLog.getTotalNum()/PAGE_SIZE;
                Long r1=appLog.getTotalNum()%PAGE_SIZE;
                if(r1!=0){
                    r0+=1;
                }
                appLog.setTotalPage(new Long(r0));
            }else{
                appLog.setTotalPage(new Long(1));
            }
            StringBuffer stringBuffer=new StringBuffer("暂无日志记录");
            int i=0;
            for (SearchHit searchHit : hits) {
                Map<String, Object> sm = searchHit.sourceAsMap();
                if(i==0){
                    stringBuffer=new StringBuffer("");
                }
                stringBuffer.append(sm.get("log").toString());
                i++;
            }
            //System.out.println("查询结果:"+stringBuffer.toString());
            appLog.setLogs(stringBuffer.toString());
            return appLog;
        }finally {
            if(client!=null){
                try {
                    baseElasticsearch.getEsDataSource().releaseClient(client);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new VenusException(VenusResponseStatus.LOG_EXCEPTION, "释放es客户端异常!");
                }
            }
        }
    }

    @Override
    public AppLog queryAppLog1(String namespaceName, String podName, String timeStart, String timeEnd, String queryKey, int showRecodes) throws VenusException {
//        System.out.println(namespaceName);
//        System.out.println(podName);
        Client client=null;
        try{
            try {
                client=baseElasticsearch.getEsDataSource().getClient();
            } catch (Exception e) {
                e.printStackTrace();
                throw new VenusException(VenusResponseStatus.LOG_EXCEPTION, "获取日志es客户端异常!");
            }
            if (StringUtil.isEmpty(podName)) {
                throw new VenusException(VenusResponseStatus.NO_CONTENT, "应用实例为空!");
            }
            BoolQueryBuilder bq= QueryBuilders.boolQuery();
//            bq.must(QueryBuilders.commonTermsQuery("kubernetes.namespace_name", namespaceName));
//            bq.must(QueryBuilders.commonTermsQuery("kubernetes.pod_name", podName));
            bq.must(QueryBuilders.termsQuery("kubernetes.namespace_name", namespaceName));
            bq.must(QueryBuilders.termsQuery("kubernetes.pod_name", podName));

            if(!StringUtil.isEmpty(queryKey)){
                bq.must(QueryBuilders.queryStringQuery(queryKey));
            }
            SortOrder sortOrder=SortOrder.DESC;//倒序查询
            if(!StringUtil.isEmpty(timeStart)&&!StringUtil.isEmpty(timeEnd)){
                String ds="";
                String de="";
                try {
                    //Wed Jan 24 2018 00:00:00 GMT 08:00
                    ds= DateUtil.dealDateFormat2(timeStart);
                    de= DateUtil.dealDateFormat2(timeEnd);
                } catch (ParseException e) {
                    throw new VenusException(VenusResponseStatus.LOG_EXCEPTION, "时间格式有误!");
                }
                bq.must(QueryBuilders.rangeQuery("@timestamp").from(ds).to(de));
            }

            SearchRequestBuilder srb = client.prepareSearch("logstash-*")
                    .setTypes("fluentd")
                            //按时间降序号
                    .addSort("@timestamp", sortOrder)
                    .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                            // 设置查询数据的位置,分页用
                    .setFrom(0)
                            // 设置查询结果集的最大条数
                    .setSize(showRecodes)
                            // 设置是否按查询匹配度排序
                    .setExplain(true);
            // 最后就是返回搜索响应信息
            srb.setQuery(bq);

            SearchResponse response =srb.execute().actionGet();
            SearchHits searchHits = response.getHits();
            SearchHit[] hits = searchHits.getHits();
            AppLog appLog=new AppLog();
            appLog.setTotalNum(searchHits.getTotalHits());
            appLog.setTotalPage(new Long(1));
            StringBuffer stringBuffer=new StringBuffer("暂无日志记录");
            //logs date range:2017/12/22 34:05:09-2017/12/22 34:00:09
            String logDateRange="";
            for (int j=hits.length-1;j>=0;j--) {
                Map<String, Object> sm = hits[j].sourceAsMap();
                System.out.println(sm.get("@timestamp").toString());
                if(j==hits.length-1){
                    stringBuffer=new StringBuffer("");
                    //2018/01/25 06:15:56
                    String fDate=sm.get("@timestamp").toString().split("\\+")[0].replaceAll("T"," ");
                    logDateRange+="日志查询结果时间范围:"+dateFormat(fDate);
                    //logDateRange+="logs date range:"+sm.get("@timestamp").toString().split("\\+")[0].replaceAll("T"," ").replaceAll("-","/");
                }
                if(j==0){
                    String tDate=sm.get("@timestamp").toString().split("\\+")[0].replaceAll("T"," ");
                    logDateRange+="至"+dateFormat(tDate);
                    //logDateRange+="-"+sm.get("@timestamp").toString().split("\\+")[0].replaceAll("T"," ").replaceAll("-","/");
                    //System.out.println(logDateRange);
                }
                stringBuffer.append(sm.get("log").toString());
            }
            //System.out.println("查询结果:"+stringBuffer.toString());
            appLog.setDateRange(logDateRange);
            appLog.setTotalRecodes(appLog.getTotalRecodes().replaceAll("0",Long.toString(searchHits.getTotalHits())));
            appLog.setLogs(stringBuffer.toString());
            return appLog;
        }finally {
            if(client!=null){
                try {
                    baseElasticsearch.getEsDataSource().releaseClient(client);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new VenusException(VenusResponseStatus.LOG_EXCEPTION, "释放es客户端异常!");
                }
            }
        }
    }


    @Override
    public AppLog queryAppLog2(String namespaceName, String podName, String timeStart, String timeEnd, String queryKey, int showRecodes) throws VenusException {
        String logs="";
        try {
            //String url="http://120.55.117.90:6363/api/v1/namespaces/venus-pro/pods/venus-log-dep-2925718498-gt549/log?tailLines=1000";
            KubernetesClient k8sClient = k8sManageService.getK8sClient();
            OkHttpClient okHttpClient= HttpClientUtils.createHttpClient(k8sClient.getConfiguration());
            URL url =k8sClient.getMasterUrl();//例如:http://10.10.40.235:23232/
            String masterUrl=url.toString();
            String url1=masterUrl+"api/v1/namespaces/"+namespaceName+"/pods/"+podName+"/log?tailLines="+showRecodes+"&pretty=true";

           logs=getLogResult(url1,okHttpClient);//业哥 注释掉 20190217
        }catch (Exception ex){
            throw new VenusException(VenusResponseStatus.LOG_EXCEPTION,ex.getMessage());
        }
        AppLog appLog=new AppLog();
        appLog.setLogs(logs);
        return appLog;
    }

    private String getLogResult(String url,OkHttpClient httpClient) throws Exception {
        String result="";
        Request request = new Request.Builder()
                .url(url)
                .build();
        Response response = httpClient.newCall(request).execute();
        int code=response.code();
        if(code==200){
            result = response.body().string();
        }else{
            result = "暂无日志记录";
        }
        return result;
    }

    private String dateFormat(String oldDateStr){
        try {
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date = df.parse(oldDateStr);
            Calendar cal = Calendar.getInstance();
            cal.setTime(date);//date 换成已经已知的Date对象
            cal.add(Calendar.HOUR_OF_DAY, +8);// after 8 hour
            String r=df.format(cal.getTime());
            return r;
        }catch (Exception e){
            return "time error";
        }
    }
}
